package struts2.sample04;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.config.Namespace;
import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;
import org.apache.struts2.dispatcher.ServletDispatcherResult;

import struts2.sample04.chinchirorin.ThreeDices;
import struts2.sample04.chinchirorin.Yaku;

/**
 * コンピューターとチンチロリンをするアクション
 * 
 * コンピューターとチンチロリンをして、勝ったら「kachi」、負けたら「make」
 * 引き分けだったら「hikiwake」を返すアクション。
 */

// NamespaceアノテーションをつけるとURLが変わる。
//   Namespaceアノテーションが無い場合  ：http://localhost:8080/sample03/chinchirorin.action
//   Namespaceアノテーションをつけた場合：http://localhost:8080/sample03/chin/chinchirorin.action
@Namespace("/chin")

// @Resultsアノテーションの中に@Resultアノテーションの配列を書く
// @Resultアノテーション
//   name:   executeメソッドの戻り値に対応する文字列
//   type:   アクション実行結果の種類？ 色んなresult-typeが用意されてる
//           ServletDispatcherResultは「実行結果としてjspとかservletを返す」って意味なんだと思う
//           ↑はデフォルトなので省略できる。
//   value:  result-typeによって意味が変わるんだろうな。
//           ServletDispatcherResultの場合はjspのファイル名を表す文字列
//           今回はNamespaceアノテーションをつけてるので、「chin」フォルダにあるjspファイル
//           ってことになるんだろう
//   params: これもresult-typeによって意味が変わるんだろうな。
//           詳しいことはまだよくわかりません。
@Results({
	@Result(name="kachi"   , type=ServletDispatcherResult.class, value="kachi.jsp", params={}),
	@Result(name="make"    , type=ServletDispatcherResult.class, value="make.jsp"),
	@Result(name="hikiwake", type=ServletDispatcherResult.class, value="hikiwake.jsp")
})
public class ChinchirorinAction {

	/** ログ */
	private static final Log LOG = LogFactory.getLog(ChinchirorinAction.class);
	
	/**
	 * アクション実行メソッド。
	 * 
	 * アクションクラスはexecuteという名前のメソッドを実装してないといけない。
	 * またこいつは引数なしで戻り値の型はStringでないといけない。
	 */
    public String execute() {
    	
    	// コンピューターがサイコロを振る
    	Yaku cpu = chinchiroThreeTime();
    	LOG.debug("cpu=["+cpu+"]");
    	
    	// コンピューターが目なし、ヒフミ、１の目のいずれかだったら人間の勝ち
    	if(cpu.isMake())
    		return "kachi";
    	
    	// コンピューターがゾロメ、シゴロ、６の目のいずれかだったら人間の負け
    	if(cpu.isKachi())
    		return "make";
    	

    	// 人間がサイコロを振る
    	Yaku hito = chinchiroThreeTime();
    	LOG.debug("hito=["+hito+"]");
    	
    	// 人間が目なし、ヒフミ、１の目のいずれかだったら人間の負け
    	if(hito.isMake())
    		return "make";
    	
    	// 人間がゾロメ、シゴロ、６の目のいずれかだったら人間の勝ち
    	if(hito.isKachi())
    		return "kachi";
    	
    	
    	// 両方とも２～４の目だった場合は目の数字で勝負
    	int cpuDeme = cpu.getNumber();
    	int hitoDeme = hito.getNumber();
    	
    	if(cpuDeme > hitoDeme)
    		return "make";
    	if(cpuDeme == hitoDeme)
    		return "hikiwake";
    	if(cpuDeme < hitoDeme)
    		return "kachi";


    	// ここまで来ることはありえないので例外
    	throw new IllegalStateException("なんだか変だわ");

    }

    
    
    /**
     * サイコロを３つ振って、目なしだったらもう一度振る。
     * ３回振って３回とも目なしだったら最後の役を返す。
     * 
     * @return サイコロの出目（×３）
     */
    private Yaku chinchiroThreeTime(){
    	
    	// 戻り値
    	Yaku result = null;
    	// 三つのサイコロを生成
    	ThreeDices threeDices = new ThreeDices();
    	
    	for(int i=0; i<3; i++){
        	// サイコロを振る
    		result = threeDices.roll();
        	LOG.debug("result=["+result+"]");
        	
        	// 目なしだったらもう一回
        	if(result == Yaku.MENASHI) 
        		continue;
        	// 役か目が付いたらそれを返す
        	else
        		break;
    	}
    	
    	return result;
    }

}
